﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace Infra.Utils.ExpressionTree
{
    public class QueryGenerator : IQueryGenerator
    {
        private static readonly Dictionary<MethodType, MethodInfo> _rule;
        private Dictionary<string, MethodType> _dic;

        static QueryGenerator()
        {
            _rule = new Dictionary<MethodType, MethodInfo>();
            _rule.Add(MethodType.StringContain, Type.GetType("System.String").GetMethod("Contains", new[] { typeof(string) }));
        }

        public MethodType this[string index]
        {
            protected get
            {
                if (this._dic == null || this._dic.ContainsKey(index) == false)
                    return MethodType.Equal;

                return this._dic[index]; 
                
            }
            set
            {
                if(this._dic == null)
                    this._dic = new Dictionary<string, MethodType>();

                this._dic[index] = value;
            }
        }

        public LambdaExpression Generate(Type type, string propertyname, object value)
        {
            var param = Expression.Parameter(type, "a");
            var property = Expression.PropertyOrField(param, propertyname);
            Expression body;

            var methodType = this[propertyname];
            if (methodType != MethodType.Equal)
            {
                if (_rule == null || _rule.ContainsKey(methodType) == false)
                    body = Expression.Equal(property, Expression.Constant(value));
                else
                    body = Expression.Call(property, _rule[methodType], Expression.Constant(value));
            }
            else
                body = Expression.Equal(property, Expression.Constant(value));

            return Expression.Lambda(body, param);
        }
    }
}
